package com.mew.chess.core.game.shbz.service;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.mew.chess.core.common.handler.ChessPushMessageUtil;
import com.mew.chess.core.common.handler.GameCommonService;
import com.mew.chess.core.common.handler.MaxBonusService;
import com.mew.chess.core.common.provide.GameFeignService;
import com.mew.chess.core.game.shbz.game.ShbzGameManager;
import com.mew.chess.core.game.shbz.game.ShbzRoomManager;
import com.mew.chess.core.game.shbz.game.ShbzTableManager;
import com.mew.chess.core.game.shbz.game.common.*;
import com.mew.chess.core.game.shbz.game.message.ArtilleryMessage;
import com.mew.chess.core.game.shbz.game.message.FishCMDMapType;
import com.mew.chess.core.game.shbz.game.message.HitResponseMessage;
import com.mew.chess.core.game.shbz.game.message.request.HitRequestMessage;
import com.mew.common.dc.redis.AucRedisService;
import com.mew.common.dc.redis.GameRoomRedisService;
import com.mew.common.dc.redis.UserProfileRedisService;
import com.mew.common.entity.config.FishingFish;
import com.mew.common.entity.config.Room;
import com.mew.common.entity.game.RoomProfile;
import com.mew.common.entity.game.WinFree;
import com.mew.common.rest.LongMessage;
import com.mew.common.rest.game.BetAfterRequest;
import com.mew.common.util.NumberUtil;
import com.zebra.common.concurrent.ZebraExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ShbzService {

    @Autowired
    private GameFeignService feignService;
    @Autowired
    private AucRedisService aucRedisService;
    @Autowired
    private UserProfileRedisService userProfileRedisService;
    @Autowired
    private ArtilleryUtils artilleryUtils;
    @Autowired
    private MaxBonusService maxBonusService;
    @Autowired
    private GameCommonService gameCommonService;
    @Autowired
    private GameRoomRedisService gameRoomRedisService;


    public LongMessage bet(long userId, int roomId, HitRequestMessage requestMessage) {
        LongMessage longMessage = new LongMessage();
        ShbzRoomManager manager = ShbzGameManager.getInstance().getController(roomId);
        ShbzTableManager table = manager.getTableByUserId(userId);
        FishUserBO fishUserBO = table.getOnlineUserMap().get(userId);

        int fishId = requestMessage.getFishId();
        int betId = requestMessage.getBetId();
        int seatId = requestMessage.getSeatId();
        int isDouble = requestMessage.getIsDouble();

        FishBO fishBO = table.getFishMap().get(fishId);

        if (fishBO!=null && fishBO.getRemainStep()*FishConstantValue.STEP_TIME<fishBO.getRuleStep()){
            FishTableLog fishTableLog = table.getFishTablelog(fishBO.getFishType());
            //活着
            int fishType = fishBO.getFishType();
            FishingFish fishingFish = ShbzGameManager.getInstance().getFish().get(fishType);
            int bet = ShbzGameManager.getInstance().getController(roomId).getBets()[betId-1]*(isDouble+1);
            long win = -bet;
            int score = 0;


            HashMap<Integer, FishLog> map = fishUserBO.getFishLogMap().get(bet);

            if (null==map){
                map = new HashMap<>();
                fishUserBO.getFishLogMap().put(bet,map);
            }

            FishLog fishLog = map.get(fishType);
            if (null==fishLog){
                fishLog = new FishLog();
                map.put(bet,fishLog);
            }

            fishTableLog.hit++;
            table.playTimes++;
            if (RandomUtil.randomInt(1000)<FishConstantValue.fishRedisValue.dodge[manager.getRoomType()-1]){
                fishLog.dodge++;
                table.dodgeTimes++;
            } else if  (fishingFish.kill()){
                fishBO = table.getFishMap().remove(fishId);
                if (null==fishBO){
                    return longMessage;
                }
                fishTableLog.kill++;
                fishLog.kill++;
                //击杀
                score = fishingFish.getScore();
                win += score*bet;

                //发消息
                long goldNumber = fishUserBO.getGoldNumber() + win;
                HitResponseMessage message = HitResponseMessage.builder().seatNo(seatId).fishId(fishId).goldNumber(goldNumber).winNumber(win+bet).maxMultiple(score).build();
//                log.info("kill fish bet:{} fishType:{} res:{}",bet,fishType,message);
                FishTableUtil.sendMsgByTable(table,message, FishCMDMapType.KillMessage.code(), 0);
                maxBonusService.addMaxBonus(userId,fishUserBO.getGameId(),win+bet,score);
            }

            addGold(fishUserBO,bet,win);
            fishTableLog.bet += bet;
            fishTableLog.payment += win+bet;
            fishLog.hit++;
            //奖励炮弹
            arti(userId, table, bet, fishUserBO);

        }

        longMessage.setL(fishUserBO.getGoldNumber());
        return longMessage;
    }

    private void arti(long userId, ShbzTableManager table, int bet, FishUserBO fishUserBO) {
        ZebraExecutor executor = ShbzGameManager.getInstance().getDisruptorByUserId(fishUserBO.getUserId());
        executor.execute(()-> {
            //炮弹
            int[] artillery = artilleryUtils.getArtillery(table.getRoomType(), bet, fishUserBO);

            if (null != artillery) {
                //炮台增加
                ArtilleryMessage message = ArtilleryMessage.builder().seatNo(fishUserBO.getSeatNo()).artillerys(artillery).build();
                ChessPushMessageUtil.pushMessage(fishUserBO.getGameSession(), FishCMDMapType.ArtilleryMessage.code(), message);
                upWinFree(userId, table.getRoomId(), table.getTableId());
            }
        });
    }

    private void addGold(FishUserBO fishUserBO,long bet,long win){
        ZebraExecutor executor = ShbzGameManager.getInstance().getDisruptorByUserId(fishUserBO.getUserId());
        executor.execute(()->{
            fishUserBO.setBet(fishUserBO.getBet()+bet);
            fishUserBO.setPayment(fishUserBO.getPayment()+(win+bet));
        });
        fishUserBO.updateGoldNumber(win);
    }


    public void payment(int roomId,int tableId){
        ShbzTableManager table = ShbzGameManager.getInstance().getController(roomId).getTable(tableId);
        ArrayList<FishUserBO> fishUserBOs = new ArrayList<>(table.getOnlineUserMap().values());
        gameCommonService.checkTMSOnline(table.getOnlineUserMap().values().stream().map(FishUserBO::getGameSession).collect(Collectors.toList()), ShbzGameManager.getInstance().getGameId(), table.getRoomId());
        for (FishUserBO userBO : fishUserBOs) {
            ZebraExecutor executor = ShbzGameManager.getInstance().getDisruptorByUserId(userBO.getUserId());
            executor.execute(()->{
                doPayment(userBO);
                aucRedisService.chessBetLock(userBO.getUserId(), FishConstantValue.OVER_TIME); //参与
            });
            table.lostConnection(userBO.getUserId());
        }


        //停止鱼潮
    }

    public void tableLog(ShbzTableManager table) {
        log.info("shbz,room{},table{},游戏次数,{},免伤次数,{},比例,{}", table.getRoomId(), table.getTableId(), table.playTimes, table.dodgeTimes, table.playTimes>0?((double) table.dodgeTimes)/ table.playTimes:0);
        table.playTimes = 0;
        table.dodgeTimes = 0;
        HashMap<Integer, FishTableLog> logMap = table.getLogMap();
        StringBuilder builder = new StringBuilder();
        logMap.forEach((k,v)->{
            double jsl = v.hit > 0 ? ((double) v.kill) / v.hit : 0;
            builder.append("room"+ table.getRoomId() +",鱼类型："+k+",攻击："+v.hit+",杀死："+v.kill + ",击杀率："+jsl +",押注："+v.bet+",赔付："+ v.payment+"\n");
        });
        log.info("shbz,room"+ table.getRoomId()+",table"+ table.getTableId()+",\n"+builder.toString());
        logMap.clear();
    }

    public void doPayment(FishUserBO userBO){

        if (userBO.getBet()==0 && userBO.getPayment()==0){
            return;
        }

        BetAfterRequest request = BetAfterRequest.builder()
                .uid(userBO.getUserId())
                .relateInoutId(userBO.getInoutId())
                .gameId(userBO.getGameId())
                .roomId(userBO.getRoomId())
                .bet(userBO.getBet())
                .payment(userBO.getPayment())
                .rollerId(0)
                .betTimes((userBO.getBet() ==0 || userBO.getPayment() < 1) ? 0 : (int) (userBO.getPayment() / userBO.getBet()))
                .iconResult("")
                .roomRecord(1)
                .betArray("")
                .paymentArray("")
                .build();

        userBO.setBet(0);
        userBO.setPayment(0);

        ArrayList<BetAfterRequest> list = new ArrayList<BetAfterRequest>() {{
            add(request);
        }};
        feignService.chessBetAfter(list);

    }

    public void upWinFree(long uid,int roomId,int tableId){
        ShbzTableManager table = ShbzGameManager.getInstance().getController(roomId).getTable(tableId);
        FishUserBO userBO = table.getOnlineUserMap().get(uid);
        if (null!=userBO && null!=userBO.getGameSession()){
            WinFree winFree = userProfileRedisService.getRedisWinfree(uid, roomId);
            winFree.setJson(JSON.toJSONString(userBO.getArtillerys()));
            userProfileRedisService.updateRedisWinfree(winFree);
        }
    }




}
